package controllers;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import play.*;
import play.mvc.*;

import models.*;

@With(Secure.class)
public class CISs extends CRUD { 

	/**
	 * Instancie des variables de session(session.put())
	 * Met ces variables dans des variables de rendu(render.args())
	 */
	@Before
	static void setConnectedUser() {
		if(Security.isConnected()) {
			if(!session.contains("agent_fullname")){
				Agent agent = Agent.find("nomUtilisateur", Security.connected()).first();
				Fonction gestFonct=Fonction.find("id_fonction like ?", "FONCT").first();
				Fonction gestTer=Fonction.find("id_fonction like ?", "TERRI").first();
				Fonction admin=Fonction.find("id_fonction like ?", "ADM").first();
				Fonction chef_CIS=Fonction.find("id_fonction like ?", "RCIS").first();
				Fonction formateur=Fonction.find("id_fonction like ?", "FOR").first();
				List<CIS> centres=CIS.find("responsable.id like ?", agent.id).fetch();
				boolean resp=!centres.isEmpty();
				/*
				 * Compte le nombre d'autorisation en attente pour les CIS où l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				List<Candidat> listeCandidats=new ArrayList<Candidat>();
				if(agent.fonction.contains(chef_CIS) || resp){
					Iterator<CIS> i=centres.iterator();
					while(i.hasNext()){
						List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
						listeCandidats.addAll(cand);
					}
					session.put("nb_demande_auto", listeCandidats.size());
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=Candidat.count("etatCandid.id_etatcandid like ? and demandeAnnulation is not true", "AVAL");
					long nbAnnulAdmin=Candidat.count("demandeAnnulation is true");
					session.put("nb_demande_valid_admin", nbValidAdmin);
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					session.put("nb_demande_annul_admin", nbAnnulAdmin);
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				/*
				 * Compte le nombre de validations et d'annulations en attente pour le groupement dont l'agent est responsable
				 * et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(gestTer)){
					long nbValidTerri=Candidat.count("etatCandid.id_etatcandid like ? and stage.structure.responsable like ? and demandeAnnulation is not true", "AVAL", agent);
					long nbAnnulTerri=Candidat.count("demandeAnnulation is true and stage.structure.responsable.id like ? and etatCandid.id_etatcandid not like ? or etatCandid.nom not like ?", agent.id, "ANN", "REF");
					session.put("nb_demande_valid_terri", nbValidTerri);
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					session.put("nb_demande_annul_terri", nbAnnulTerri);
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				
				/*
				 * Création des variables de session
				 */
				
				/*
				 * groupementResp_id représente l'id du groupement de l'agent si celui-ci est le responsable
				 * Sinon l'id du groupement auquel il appartient s'il possède la fonction gestionnaireTerritorial
				 */
				Groupement gpmt=Groupement.find("responsable like ?", agent).first();
				if(gpmt!=null){
					session.put("groupementResp_id", gpmt.id);
				}
				else if(agent.fonction.contains(gestTer)){
					session.put("groupementResp_id", agent.cis.groupement.id);
				}
				
				int aujourdhui=Calendar.getInstance().get(Calendar.YEAR);
				session.put("nomUtilisateur", agent.nomUtilisateur);
				session.put("anneeEnCours", aujourdhui);
				session.put("agent_id", agent.id);
				session.put("agent_niv", agent.niv.niv);
				session.put("agent_cis", agent.cis);
				session.put("agent_grpt", agent.cis.groupement);
				session.put("chef_CIS", agent.fonction.contains(chef_CIS));
				session.put("agent_email", agent.email);
				session.put("agent_fullname", agent.fullname());
				session.put("agent_responsable", resp);
				session.put("agent_grade", agent.grade.toString());
				session.put("gestionnaireFonct", (agent.fonction.contains(gestFonct)));
				session.put("gestionnaireTerri", agent.fonction.contains(gestTer));
				session.put("formateur", agent.fonction.contains(formateur));
				session.put("admin", agent.fonction.contains(admin));
				session.put("CISService", agent.cis.nom);
				/*
				 * Compte le nombre de validations en attente pour les fmpa et l'ajoute à une variable de session et de rendu.
				 */
				if(agent.fonction.contains(admin) || agent.fonction.contains(gestFonct)){
					long nbValidAdmin=FMPA.count("etat.nom like ?", "Attente de validation");
					session.put("nb_valid_fmpa", nbValidAdmin);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(gestTer)){
					long nbValidTerri=FMPA.count("etat.nom like ? and cis.groupement.nom like ?", "Attente de validation", session.get("agent_grpt"));
					session.put("nb_valid_fmpa", nbValidTerri);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}else if(agent.fonction.contains(chef_CIS) || resp){
					long nbValidCis=FMPA.count("etat.nom like ? and cis.nom like ?", "Attente de validation", session.get("CISService"));
					session.put("nb_valid_fmpa", nbValidCis);
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				/*
				 * Création des variables de rendu
				 */
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				if(agent.niv.id != 0){
					session.put("agent_for", agent.niv);
					renderArgs.put("agent_for", session.get("agent_for"));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
			else{
				/*
				 * Création des variables de rendu si les variables de session existent
				 */
				if(session.contains("nb_demande_valid_terri") || session.contains("nb_demande_annul_terri")){
					renderArgs.put("nb_demande_valid_terri", Integer.parseInt(session.get("nb_demande_valid_terri")));
					renderArgs.put("nb_demande_annul_terri", Integer.parseInt(session.get("nb_demande_annul_terri")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				if(session.contains("nb_demande_valid_admin") || session.contains("nb_demande_annul_admin")){
					renderArgs.put("nb_demande_valid_admin", Integer.parseInt(session.get("nb_demande_valid_admin")));
					renderArgs.put("nb_demande_annul_admin", Integer.parseInt(session.get("nb_demande_annul_admin")));
				}
				if(session.contains("nb_demande_auto")){
					renderArgs.put("nb_demande_auto", Integer.parseInt(session.get("nb_demande_auto")));
				}
				renderArgs.put("anneeEnCours", Integer.parseInt(session.get("anneeEnCours")));
				renderArgs.put("CISService", session.get("CISService"));
				renderArgs.put("agent_niv", Integer.parseInt(session.get("agent_niv")));
				renderArgs.put("agent_grpt", session.get("agent_grpt"));
				renderArgs.put("chef_CIS", session.get("chef_CIS").equals("true"));
				renderArgs.put("admin", session.get("admin").equals("true"));
				renderArgs.put("formateur", session.get("formateur").equals("true"));
				renderArgs.put("agent_email", session.get("agent_email"));
				renderArgs.put("agent_fullname", session.get("agent_fullname"));
				renderArgs.put("agent_responsable", session.get("agent_responsable").equals("true"));
				renderArgs.put("agent_grade", session.get("agent_grade"));
				renderArgs.put("gestionnaireFonct", session.get("gestionnaireFonct").equals("true"));
				renderArgs.put("gestionnaireTerri", session.get("gestionnaireTerri").equals("true"));
				renderArgs.put("agent_for", session.get("agent_for"));
				if(session.contains("nb_valid_fmpa")){
					renderArgs.put("nb_valid_fmpa", Integer.parseInt(session.get("nb_valid_fmpa")));
				}
				if(session.contains("groupementResp_id")){
					renderArgs.put("groupementResp_id", Long.parseLong(session.get("groupementResp_id")));
				}
				Calendar c=Calendar.getInstance();
				renderArgs.put("Annee", c.get(Calendar.YEAR));
			}
		}
	}

	/**
	 * action permettant d'afficher les candidatures que l'agent peut autoriser pour le CISService
	 * dont l'id est passé en paramètre
	 * @param id l'id du CISService dont les candidatures doivent etre autorisées
	 */
	public static void autorisationCandidatures(){
		List<Candidat> listeCandidats=new ArrayList<Candidat>();
		List<CIS> centres=new ArrayList<CIS>();
		List<OrdresPriorite> priorites=OrdresPriorite.findAll();
		/*
		 * Vérifie si l'utilisateur connecté à la fonction ResponsableCISService
		 */
		if(session.get("chef_CIS").equals("true")){
			centres=CIS.find("responsable.nomUtilisateur like ?", session.get("nomUtilisateur")).fetch();
			/*
			 * Si l'utilisateur a les droits, alors il est responsable de la formation de son centre
			 * Affiche les candidatures de son centre en attente d'autorisation
			 */
			if(centres.isEmpty()){
				CIS agentCis=CIS.find("nom like ?", session.get("agent_cis")).first();
				List<Candidat> c=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", agentCis.id, "AAUT").fetch();
				listeCandidats.addAll(c);
			}
			/*
			 * S'il est responsable d'un ou plusieurs centre(s)/service(s)
			 * Affiche les candidatures en attente d'autorisation de son(ses) centre(s)/service(s)
			 */
			else{
				Iterator<CIS> i=centres.iterator();
				while(i.hasNext()){
					List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
					listeCandidats.addAll(cand);
				}
			}

			render(listeCandidats, priorites);
		}
		else{
			render("@accessDenied");
		}
	}

	/**
	 * Même fonctionnement que pour autorisationCandidatures() 
	 * L'admin peut voir toutes les candidatures du département
	 */
	public static void autorisationCandidaturesAdmin(){
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true")){
			List<OrdresPriorite> priorites=OrdresPriorite.findAll();
			List<Candidat> listeCandidats=new ArrayList<Candidat>();
			List<CIS> centres=CIS.find("order by nom").fetch();
			listeCandidats=Candidat.find("etatCandid.id_etatcandid like ?", "AAUT").fetch();
			render(centres, listeCandidats, priorites);
		}
		else{
			render("@accessDenied");
		}
	}


	/**
	 * Affiche toutes les candidatures du centre/service.
	 */
	public static void voirCandid(){
		List<CIS> centres=new ArrayList<CIS>();
		List<Candidat> candidats=new ArrayList<Candidat>();
		if(session.get("chef_CIS").equals("true")){
			centres=CIS.find("responsable.nomUtilisateur like ?", session.get("nomUtilisateur")).fetch();
			/*
			 * Si l'utilisateur a les droits, alors il est responsable de la formation de son centre
			 * Affiche les candidatures de son centre en attente d'autorisation
			 */
			if(centres.isEmpty()){
				CIS agentCis=CIS.find("nom like ?", session.get("agent_cis")).first();
				List<Candidat> c=Candidat.find("agent.cis.id like ?", agentCis.id).fetch();
				candidats.addAll(c);
			}
			/*
			 * S'il est responsable d'un ou plusieurs centre(s)/service(s)
			 * Affiche les candidatures en attente d'autorisation de son(ses) centre(s)/service(s)
			 */
			else{
				Iterator<CIS> i=centres.iterator();
				while(i.hasNext()){
					List<Candidat> cand=Candidat.find("agent.cis.id like ? ", i.next().id).fetch();
					candidats.addAll(cand);
				}
			}
			render(candidats);
		}
		else{
			render("@accessDenied");
		}
	}

	/**
	 * Change l'état des candidatures en "En attente validation" si l'autorisation est accordée
	 * "Refusée" sinon
	 */
	public static void envoieAutorisation(){
		/*
		 * Récupération de la liste des candidatures en attente d'autorisation du CIS de l'agent connecté
		 */
		List<CIS> centres=new ArrayList<CIS>();
		List<Candidat> candidatures=new ArrayList<Candidat>();
		centres=CIS.find("responsable.nomUtilisateur like ?", session.get("nomUtilisateur")).fetch();
		if(centres.isEmpty()){
			CIS agentCis=CIS.find("nom like ?", session.get("agent_cis")).first();
			List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", agentCis.id, "AAUT").fetch();
			candidatures.addAll(cand);
		}
		Iterator<CIS> i=centres.iterator();
		while(i.hasNext()){
			List<Candidat> cand=Candidat.find("agent.cis.id like ? and etatCandid.id_etatcandid like ?", i.next().id, "AAUT").fetch();
			candidatures.addAll(cand);
		}
		Iterator<Candidat> itCandid=candidatures.iterator();
		EtatCandid etatOK=EtatCandid.find("id_etatcandid like ?", "AVAL").first();
		EtatCandid etatNON=EtatCandid.find("id_etatcandid like ?", "NAUT").first();
		/*
		 * Boucle sur les candidatures affichées et change l'état de la candidature en fonction de l'état du bouton radio
		 */
		OrdresPriorite prio=null;
		while(itCandid.hasNext()){
			Candidat candidat=itCandid.next();
			int nbAuto=Integer.parseInt(session.get("nb_demande_auto"));
			/*
			 * Si le bouton radio oui a été coché passe la candidature en état "En attente validation"
			 */
			if(params.get(""+candidat.id)!=null){
				if(params.get(""+candidat.id).equals("oui")){
					nbAuto--;
					session.put("nb_demande_auto", nbAuto);
					if(Long.decode(params.get("priorite"+candidat.id))!=0){
						if(Long.decode(params.get("priorite"+candidat.id))!=0){
							prio=OrdresPriorite.findById(Long.decode(params.get("priorite"+candidat.id)));
						}
						candidat.ordrePrioriteCis=prio;
					}
					candidat.setEtatCandid(etatOK);
					candidat.save();
				}
				/*
				 * sinon si la case Non a été coché, passage en état "non autorisé"
				 */
				else if(params.get(""+candidat.id).equals("non")){
					nbAuto--;
					session.put("nb_demande_auto", nbAuto);
					candidat.etatCandid=etatNON;
					candidat.motifRefus=params.get("motif"+candidat.id);
					candidat.save();
				}
			}
		}
		autorisationCandidatures();
	}

	/**
	 * Change l'état des candidatures en "En attente validation" si l'autorisation est accordée par un admin
	 * ou un gestionnaire fonctionnel ou territorial, "Refusée" sinon
	 */
	public static void envoieAutorisationAdmin(){
		/*
		 * Récupération de la liste des candidatures en attente d'autorisation du CIS de l'agent connecté
		 */
		List<Candidat> candidatures=new ArrayList<Candidat>();
		/*
		 * Si l'agent est admin récupère toutes les candidatures
		 */
		if(session.get("admin").equals("true") || session.get("gestionnaireFonct").equals("true")){
			candidatures=Candidat.find("etatCandid.id_etatcandid like ?", "AAUT").fetch();
		}
		Iterator<Candidat> itCandid=candidatures.iterator();
		EtatCandid etatOK=EtatCandid.find("id_etatcandid like ?", "AVAL").first();
		EtatCandid etatNON=EtatCandid.find("id_etatcandid like ?", "NAUT").first();
		/*
		 * Boucle sur les candidatures affichées et change l'état de la candidature en fonction de l'état du bouton radio
		 */
		OrdresPriorite prio=null;
		while(itCandid.hasNext()){
			Candidat candidat=itCandid.next();
			/*
			 * Si le bouton radio oui a été coché passe la candidature en état "En attente validation"
			 */
			if(params.get(""+candidat.id)!=null){
				if(params.get(""+candidat.id).equals("oui")){
					if(Long.decode(params.get("priorite"+candidat.id))>0){
						prio=OrdresPriorite.findById(Long.decode(params.get("priorite"+candidat.id)));
						candidat.ordrePrioriteCis=prio;
					}
					candidat.setEtatCandid(etatOK);
					candidat.save();
				}
				/*
				 * sinon si la case Non a été coché, passage en état "non autorisé"
				 */
				else if(params.get(""+candidat.id).equals("non")){
					candidat.etatCandid=etatNON;
					candidat.motifRefus=params.get("motif"+candidat.id);
					candidat.save();
				}
			}
		}
		autorisationCandidaturesAdmin();
	}

}